package Network;


/**
 * Class to create the appropriate message from a byte array, received from the 
 * 
 * 
 * @author Sam Davies BBCR&D 2009
 */
public class MessageParseer {

    private char magic_0Hex = 0xe298;
    private char cellEntryHex = 0x1b1;
    private char cellExitHex = 0x12e;
    private char locationMessageHex = 0x26a;
    private char uplinkOnlyHex = 0x13d;
    private char buttonMessageHex = 0xbd;

    /**
     * An empty constructor is used as no variables or functions are accessable.
     */
    public MessageParseer() {
    }
    /**
     * Parses the bytes and creates the correct Message depending upon the 
     * magic_1, identifying the message type
     * 
     * @param buf the 52 bytes of the message
     * @return A message for the correct type.
     */

    public Message parseMessage(byte[] buf) {
        //Parse the magic_1 byte to determine message
        char magic_1 = (char) ((0xff & buf[2]) << 8 | 0xff & buf[3]);
        Message message = null;

        if (magic_1 == locationMessageHex) {
            message = parseLocationMessage(buf);
        } else if (magic_1 == buttonMessageHex) {
            message = parseButtonMessage(buf);
        } else if (magic_1 == cellEntryHex) {
            message = parseCellEntryMessage(buf);
        } else if (magic_1 == cellExitHex) {
            message = parseCellExitMessage(buf);
        } else if (magic_1 == uplinkOnlyHex) {
            message = parseUplinkOnlyMessage(buf);
        }
        return message;
    }

    private CellEntryMessage parseCellEntryMessage(byte[] buf) {
        long tag_id_bottom = ((long) (buf[4]) << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]);
        long slot = ((long) (buf[8]) << 24 | (buf[9] & 0xff) << 16 | (buf[10] & 0xff) << 8 | (buf[11] & 0xff)) & 0xFFFFFFFFL;
        long cell = ((long) (0xff & buf[12]) << 24 | 0xff & buf[13] << 16 | 0xff & buf[14] << 8 | 0xff & buf[15]) & 0xFFFFFFFFL;
        CellEntryMessage cellEntryMessage = new CellEntryMessage(cellEntryHex, tag_id_bottom, slot, cell);
        return cellEntryMessage;

    }

    private CellExitMessage parseCellExitMessage(byte[] buf) {
        long tag_id_bottom = ((long) (buf[4]) << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]);
        long slot = ((long) (buf[8]) << 24 | (buf[9] & 0xff) << 16 | (buf[10] & 0xff) << 8 | (buf[11] & 0xff)) & 0xFFFFFFFFL;
        long cell = ((long) (0xff & buf[12]) << 24 | 0xff & buf[13] << 16 | 0xff & buf[14] << 8 | 0xff & buf[15]) & 0xFFFFFFFFL;
        CellExitMessage cellExitMessage = new CellExitMessage(cellExitHex, tag_id_bottom, slot, cell);
        return cellExitMessage;
    }

    private LocationMessage parseLocationMessage(byte[] buf) {
        long tag_id_top = 0;
        long tag_id_bottom = 0;
        long flags = 0;
        float x = 0;
        float y = 0;
        float z = 0;
        float gdop = 0;
        float error = 0;
        long slot = 0;
        long slot_interval = 0;
        long slot_delay = 0;
        long cell;


        tag_id_top = ((long) (0xff & buf[4]) << 24 | 0xff & buf[5] << 16 | 0xff & buf[6] << 8 | 0xff & buf[7]) & 0xFFFFFFFFL;

        tag_id_bottom = ((long) (buf[8]) << 24 | buf[9] << 16 | buf[10] << 8 | buf[11]);

        flags = ((long) (buf[12]) << 24 | buf[13] << 16 | buf[14] << 8 | buf[15]);

        x = Float.intBitsToFloat(((buf[16]) << 24 | (buf[17] & 0xff) << 16 | (buf[18] & 0xff) << 8 | (buf[19] & 0xff)) & 0xFFFFFFFF);

        y = Float.intBitsToFloat(((buf[20]) << 24 | (buf[21] & 0xff) << 16 | (buf[22] & 0xff) << 8 | (buf[23] & 0xff)) & 0xFFFFFFFF);
        z = Float.intBitsToFloat(((buf[24]) << 24 | (buf[25] & 0xff) << 16 | (buf[26] & 0xff) << 8 | (buf[27] & 0xff)) & 0xFFFFFFFF);


        gdop = Float.intBitsToFloat(((buf[28]) << 24 | (buf[29] & 0xff) << 16 | (buf[30] & 0xff) << 8 | (buf[31] & 0xff)) & 0xFFFFFFFF);
        error = Float.intBitsToFloat(((buf[32]) << 24 | (buf[33] & 0xff) << 16 | (buf[34] & 0xff) << 8 | (buf[35] & 0xff)) & 0xFFFFFFFF);

        slot = ((long) (buf[36]) << 24 | (buf[37] & 0xff) << 16 | (buf[38] & 0xff) << 8 | (buf[39] & 0xff)) & 0xFFFFFFFFL;
        slot_interval = ((long) (buf[40]) << 24 | (buf[41] & 0xff) << 16 | (buf[42] & 0xff) << 8 | (buf[43] & 0xff)) & 0xFFFFFFFFL;
        slot_delay = ((long) (0xff & buf[44]) << 24 | 0xff & buf[45] << 16 | 0xff & buf[46] << 8 | 0xff & buf[47]) & 0xFFFFFFFFL;

        cell = ((long) (0xff & buf[48]) << 24 | 0xff & buf[49] << 16 | 0xff & buf[50] << 8 | 0xff & buf[51]) & 0xFFFFFFFFL;

        LocationMessage locationMessage = new LocationMessage(locationMessageHex, tag_id_top, tag_id_bottom, flags, x, y, z, gdop, error, slot, slot_interval, slot_delay, cell);

        return locationMessage;

    }

    private UplinkOnlyMessage parseUplinkOnlyMessage(byte[] buf) {
        long tag_id_bottom = ((long) (buf[8]) << 24 | buf[9] << 16 | buf[10] << 8 | buf[11]);
        long slot = ((long) (buf[12]) << 24 | (buf[13] & 0xff) << 16 | (buf[14] & 0xff) << 8 | (buf[15] & 0xff)) & 0xFFFFFFFFL;
        long cell = ((long) (0xff & buf[16]) << 24 | 0xff & buf[17] << 16 | 0xff & buf[18] << 8 | 0xff & buf[19]) & 0xFFFFFFFFL;
        char trembleSwitch = (char) ((buf[20] & 0xff) << 8 | (buf[21] & 0xff));
        char rssi = (char) ((buf[18] & 0xff) << 8 | (buf[19] & 0xff));

        UplinkOnlyMessage uplinkOnlyMessage = new UplinkOnlyMessage(uplinkOnlyHex, tag_id_bottom, slot, cell, trembleSwitch, rssi);
        return uplinkOnlyMessage;

    }

    private ButtonMessage parseButtonMessage(byte[] buf) {
        //long tag_id_top = ((long) (0xff & buf[4]) << 24 | 0xff & buf[5] << 16 | 0xff & buf[6] << 8 | 0xff & buf[7]) & 0xFFFFFFFFL;

        long tag_id_bottom = ((long) (buf[4]) << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]);
        long slot = ((long) (buf[8]) << 24 | (buf[9] & 0xff) << 16 | (buf[10] & 0xff) << 8 | (buf[11] & 0xff)) & 0xFFFFFFFFL;
        char orange = (char) ((buf[12] & 0xff) << 8 | (buf[13] & 0xff));
        char blue = (char) ((buf[12] & 0xff) << 8 | (buf[13] & 0xff));

        ButtonMessage buttonMessage = new ButtonMessage(buttonMessageHex, tag_id_bottom, slot, orange, blue);
        return buttonMessage;
    }
}
